Vor einiger Zeit ist mir ein interessanter Chip über den Weg gelaufen mit dem man eine Tastatur mit I2C Schnittstelle realisieren kann. Ich habe ihn mir in Februar bestellt und seitdem lag das Teil auf meinem Tisch rum. Ich spielte mit den Gedanken, sowas Ähnliches wie Pocket C.H.I.P zu bauen. Die Kosten für den ersten Prototypen haben mich etwas abgeschreckt (bzw. tun es immer noch). Außerdem hatte ich zu der damaligen Zeit noch kein Ersatz für EAGLE gefunden. Vor einigen Wochen fand ich die ESD-Tüte mit den Keypad ICs. Ich setzte mich hin und fing an ein Schaltplan zu entwerfen.
Wichtiger Hinweis
Dieser Artikel ist eine reine Beschreibung, wie ich das zum Laufen gebracht habe und keine Anleitung! D.h. einige Sachen könnten fehlen, fehlerhaft oder nach einiger Zeit einfach nicht mehr aktuell sein.
TCA8418 I2C Keypad Scanner
Zuerst einige Daten zum IC. Das Gehäuse ist in meinem Fall ein WQFN24 (es gibt auch eine Ausführung als BGA) und ist 4x4mm groß. Es verfügt über 18 GPIOs (ESD geschützt) und bietet die Möglichkeit bis zu 80 Tasten anzuschließen. Spannungsversorgung 1,65V – 3,6V. Ein Output-Pin für den Interrupt ist auch vorhanden. I2C Clock bis zu 1MHz (Fast Mode Plus). Die Typischen Anwendungen sind Smartphones, Tablets, HMI, GPS Geräte, MP3 Player und Digitalkameras.
Tastenbelegung
Bei der Tastenbelegung habe ich versucht, mich an das Beispiel von Pocket C.H.I.P zu halten, Als ich mir auch die Schaltpläne angeschaut habe, war ich etwas überrascht. Auch hier wurde ein TCA8418 verbaut. Also habe ich die Anbindung und Anordnung der Tasten fast identisch gehalten. Einige Tasten habe ich weggelassen. Die Anzahl der Taster liegt bei 55 Stück. Als Layout habe ich die US Version gewählt.
Schaltplan
Die Beschattung ist recht überschaubar. Die Anordnung der Tasten erinnert stark an die übliche Matrix-Tastaturen. Die I/O sind auch in zwei Gruppen unterteilt: 8 Zeilen (Row) und 10 Spalten (Column). Die unbenutzten I/Os werden über Pull-Ups mit der Versorgungsspannung verbunden. Die restlichen I/Os (I2C, INT, RST) habe ich auch mit Pull-Ups versehen und dazu noch einige Platzhalter für Tiefpassfilter, die ich aber zum Glück nicht gebraucht habe.
TCA8418 I2C Keyboard Schaltplan
PCB Layout
Zuerst die Frage klären, wie sich die Form des Boards ergeben hat. Die Antwort ist einfach: aus reiner Langeweile 😉 Ich habe mir nichts dabei gedacht, sondern einfach nur fast willkürlich die Linien gezogen.
Die Platine besteht aus zwei Lagen. Die Tastenbeschriftung ist leider nicht so fancy, wie bei dem PocketCHIP, aber für den ersten Prototypen ausreichend. Die Platine habe ich mit CircuitStudio entworfen. CS ist momentan das Tool, was ich für die Entwicklung von Schaltplänen und PCB Layouts verwende. Routing ist relativ einfach, da langsame Signale, kaum Strom und genug Platz. Das Einzige, worauf ich geachtet habe, dass kein Signal von einem Taster, unter einem anderen verläuft. Wenn es notwendig war, habe ich auf andere Lage gewechselt. Der innere Aufbau des Tasters ist mir unbekannt. Es kann passieren, dass beim Betätigen von einem Taster ein Übersprechen auf die darunter liegende Leiterbahn stattfindet. Das Risiko ist minimal, aber ich wollte auf Nummer sicher gehen. Die Platine wollte ich manuell löten, daher habe ich die Masseflächen um den IC, die Widerstände und Kondensatoren herum etwas weiter weg platziert und die GND Pins mit Leiterbaahnen an diese Massefläche gezogen. Das macht das Löten etwas bequemer. Das Layout war übrigens angelehnt and das von PocketCHIP
Software
I2C Test
Pinbelegung
Pin Keypad | Pin Raspberry Pi Zero |
3,3V | 3,3V (Pin 1) |
SCL | SCL (Pin 3) |
SDA | SDA (Pin 5) |
GND | GND (Pin 6) |
INT | GPIO18 (Pin 12) |
Reset | Braucht man nicht |
I2C Tools installieren und testen, ob ein Busteilnehmer mit der Adresse 34 gefunden wird.
1 2 3 4 |
sudo apt update sudo apt upgrade sudo apt install i2c-tools i2c-detect -y 1 |
Der Chip wurde sauber erkannt
1 2 3 4 5 6 7 8 9 10 |
pi@raspberrypi:~/linux/drivers/input/keyboard $ i2cdetect -y 1 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- 34 -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- -- |
Treiber/Kernel bauen
Eigentlich wollte ich das nicht machen. Ich bin auf diesem Gebiet noch etwas unerfahren und bei meinem letzten Projekt, bei dem ich Bootloader etc. bauen musste, hat es etwas Zeit und Nerven gekostet, die passenden Sources etc. zu finden und es fehlerfrei zu kompilieren. Und als ich vor einigen Jahren was für den Pi bauen musste, ging’s mir ähnlich.
Ich habe für dieses Projekt nach fertigen Treibern und nach einem einfacheren Weg gesucht, doch nichts gefunden. Gut! Bringt alles nix. Musste ich selber bauen. An dieser Stelle muss ich aber die Devs hinter dem Pi echt loben. Die „Kompiliererei“ ist gut und übersichtlich dokumentiert und der ganze Vorgang, den neuen Kernel zu kompilieren ist tadellos durchgelaufen und hat am Ende sogar funktioniert und warf mir in der Konsole keine Kernel Panic raus 🙂 Das Kompilieren auf dem Zero hat übrigens so um die 20 Stunden gedauert.
Übrigens! Damit ich gleich nach dem Flachen der SD-Karte für den Pi alles über SSH machen konnte, habe ich mir direkt eine WLAN Verbindung konfiguriert und zwar nach dieser Anleitung
Ich werfe an dieser Stelle noch die Kernel Version mit rein
1 2 |
pi@raspberrypi:~ $ uname -a Linux raspberrypi 4.14.77+ #1 Sun Oct 21 08:44:24 UTC 2018 armv6l GNU/Linux |
Beim Bauen bin ich nach diesen zwei Anleitungen vorgegangen. Die erste, wie man allgemein ein Kernel für den Pi baut. Irgendwo in der Mitte wird dann auf die zweite Anleitung verwiesen, falls man ihn anders konfigurieren möchte.
https://www.raspberrypi.org/documentation/linux/kernel/building.md
https://www.raspberrypi.org/documentation/linux/kernel/configuring.md
Als es dann um die Kernel-Config ging, das Modul TCA8418 mit „Y“ gesetzt.
Device Tree Overlay
Beim erstellen des DT-Overlays war mir der Blog von Mozzwald eine große Hilfe. Im Prinzip macht er mit diesem Projekt das, wofür ich noch zu geizig bin 😉
Overlay in /boot/overlays einfügen. Overlay ist noch aus einem frühen Stadium, könnte also Fehler beinhalten 😉
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
/dts-v1/; /plugin/; /{ compatible = "brcm,bcm2708"; fragment@0 { target = <&i2c1>; __overlay__{ tca8418@34 { compatible = "ti,tca8418"; reg = <0x34>; /* the interrupt is specified as: * The first cell is the GPIO number. * The second cell is used to specify flags: * bits[3:0] trigger type and level flags: * 1 = low-to-high edge triggered. * 2 = high-to-low edge triggered. * 4 = active high level-sensitive. * 8 = active low level-sensitive. */ irq-gpio = <&gpio 18 0x2>; /* IRQF_TRIGGER_FALLING */ interrupts = <18 2>; /* high-to-low edge triggered */ interrupt-parent = <&gpio>; interrupt-controller; keypad,num-rows = <8>; keypad,num-columns = <10>; /* row | column | key-code ex: 04,08,0010 q key */ linux,keymap = < 0x0000000d //EQUAL 0x00010002 //1 0x00020003 //2 0x00030004 //3 0x00040005 //4 0x00050006 //5 0x00060007 //6 0x00070008 //7 0x00080009 //8 0x0009000a //9 0x01000010 //Q 0x01010011 //W 0x01020012 //E 0x01030013 //R 0x01040014 //T 0x01050015 //Y 0x01060016 //U 0x01070017 //I 0x01080018 //O 0x01090019 //P 0x0200001e //A 0x0201001f //S 0x02020020 //D 0x02030021 //F 0x02040022 //G 0x02050023 //H 0x02060024 //H 0x02070025 //J 0x02080026 //K 0x0209001C //ENTER 0x0300000f //TAB 0x0301002c //Z 0x0302002d //X 0x0303002e //C 0x0304002f //V 0x03050030 //B 0x03060031 //N 0x03070032 //M 0x03080067 //UP 0x0309006c //DOWN 0x04000001 //ESC 0x04010038 //ALT right 0x04020064 //ALT left 0x04030039 //SPACE 0x0404001d //CTRL 0x04050035 //SLASH 0x04060036 //RIGHTSHIFT 0x04080069 //LEFT 0x0409006a //RIGHT 0x0500002a //LEFTSHIFT 0x0501000b //0 0x0502000c //MINUS 0x0503000e //BACKSPACE 0x05040034 //DOT >; }; }; }; }; |
DT-Overlay kompilieren
1 |
sudo dtc -@ -I dts -O dtb -o tca8418.dtbo tca8418.dts |
Der Vorgang spuckte einige Fehler / Warnungen aus, die ich erstmal ignoriert habe.
1 2 3 4 |
tca8418.dtbo: Warning (reg_format): "reg" property in /fragment@0/__overlay__/tca8418@34 has invalid length (4 bytes) (#address-cells == 2, #size-cells == 1) tca8418.dtbo: Warning (unit_address_vs_reg): Node /fragment@0 has a unit name, but no reg property tca8418.dtbo: Warning (avoid_default_addr_size): Relying on default #address-cells value for /fragment@0/__overlay__/tca8418@34 tca8418.dtbo: Warning (avoid_default_addr_size): Relying on default #size-cells value for /fragment@0/__overlay__/tca8418@34 |
Außerdem muss noch die Datei /boot/config.txt um folgenden Eintrag ergänzt werden.
dtoverlay=tca8418
Rebootet und geschaut, ob das Keypad sich irgendwie sichtbar macht.
1 2 3 4 |
pi@raspberrypi:~ $ dmesg | grep i2c [ 4.069592] i2c /dev entries driver [ 8.843265] input: tca8418 as /devices/platform/soc/20804000.i2c/i2c-1/1-0034/input/input0 pi@raspberrypi:~ $ |
Checken, ob das Eingabegerät bei Tastendruck etwas ausspuckt
1 2 3 4 5 6 7 8 |
pi@raspberrypi:/boot/overlays $ cat /dev/input/event0 V?[??QV?[?? V?[??V?[??QV?[?? V?[??V?[2F QV?[2F V?[2F V?[Y? |
Immer wenn man ich Taste betätigt habe, wurde eine „Buchstabensuppe“ ausgegeben. Damit man das auch in Klartext lesen kann, habe ich mir das Programm evtest installiert.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
pi@raspberrypi:/boot/overlays $ sudo evtest /dev/input/event0 | grep EV_KEY Event type 1 (EV_KEY) Event: time 1540314435.416024, type 1 (EV_KEY), code 16 (KEY_Q), value 1 Event: time 1540314435.540462, type 1 (EV_KEY), code 16 (KEY_Q), value 0 Event: time 1540314436.610922, type 1 (EV_KEY), code 17 (KEY_W), value 1 Event: time 1540314436.685645, type 1 (EV_KEY), code 17 (KEY_W), value 0 Event: time 1540314437.562458, type 1 (EV_KEY), code 18 (KEY_E), value 1 Event: time 1540314437.662112, type 1 (EV_KEY), code 18 (KEY_E), value 0 Event: time 1540314438.414409, type 1 (EV_KEY), code 19 (KEY_R), value 1 Event: time 1540314438.588845, type 1 (EV_KEY), code 19 (KEY_R), value 0 Event: time 1540314439.239903, type 1 (EV_KEY), code 20 (KEY_T), value 1 Event: time 1540314439.364442, type 1 (EV_KEY), code 20 (KEY_T), value 0 Event: time 1540314443.615618, type 1 (EV_KEY), code 21 (KEY_Y), value 1 Event: time 1540314443.665419, type 1 (EV_KEY), code 21 (KEY_Y), value 0 |
Keymap anpassen / erweitern
Jede Taste ist mit mehr als nur einer Funktion belegt. Deswegen benötigt man eine angepasste Keymap. Zuerst eine Datei z.b. im home Verzeichnis anlegen i2c-keypad.map
Dann folgt ein leichtes Umdenken. Wenn bei der Tastenzuweisung im Overlay mit Hexadezimal gearbeitet wurde, arbeitet man hier mit dezimalen Zahlen. Auch hier hat mir die Webseite von Mozzwald sehr geholfen. So sah meine keymap anschließend aus.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 |
keymaps 0-2,3-5,8-9,12 keycode 1 = Escape shift altgr keycode 1 = Break keycode 2 = one shift keycode 2 = exclam altgr keycode 2 = F1 keycode 3 = two shift keycode 3 = at altgr keycode 3 = F2 keycode 4 = three shift keycode 4 = numbersign altgr keycode 5 = F3 keycode 5 = four shift keycode 5 = dollar altgr keycode 5 = F4 keycode 6 = five shift keycode 6 = percent altgr keycode 6 = F5 keycode 7 = six shift keycode 7 = asciicircum altgr keycode 7 = F6 keycode 8 = seven shift keycode 8 = ampersand altgr keycode 8 = F7 keycode 9 = eight shift keycode 9 = asterisk altgr keycode 9 = F8 keycode 10 = nine shift keycode 10 = parenleft altgr keycode 10 = F9 keycode 11 = zero shift keycode 11 = parenright altgr keycode 11 = F10 keycode 12 = minus shift keycode 12 = underscore keycode 13 = plus shift keycode 13 = equal keycode 14 = BackSpace altgr keycode 14 = Remove keycode 15 = Tab keycode 16 = +q shift keycode 16 = +Q control keycode 16 = Control_q keycode 17 = +w shift keycode 17 = +W altgr keycode 17 = asciitilde control keycode 17 = Control_w keycode 18 = +e shift keycode 18 = +E control keycode 18 = Control_e keycode 19 = +r shift keycode 19 = +R control keycode 19 = Control_r keycode 20 = +t shift keycode 20 = +T control keycode 20 = Control_t keycode 21 = +y shift keycode 21 = +Y altgr keycode 21 = braceleft control keycode 21 = Control_y keycode 22 = +u shift keycode 22 = +U altgr keycode 22 = braceright control keycode 22 = Control_u keycode 23 = +i shift keycode 23 = +I altgr keycode 23 = bracketleft control keycode 23 = Control_i keycode 24 = +o shift keycode 24 = +O altgr keycode 24 = bracketright control keycode 24 = Control_o shift altgr keycode 24 = degree keycode 25 = +p shift keycode 25 = +P altgr keycode 25 = bar control keycode 25 = Control_p keycode 26 = keycode 27 = keycode 28 = Return keycode 29 = SControl keycode 30 = +a shift keycode 30 = +A control keycode 30 = Control_a keycode 31 = +s shift keycode 31 = +S control keycode 31 = Control_s shift control keycode 31 = Control_s keycode 32 = +d shift keycode 32 = +D control keycode 32 = Control_d keycode 33 = +f shift keycode 33 = +F control keycode 33 = Control_f keycode 34 = +g shift keycode 34 = +G control keycode 34 = Control_g keycode 35 = +h shift keycode 35 = +H control keycode 35 = BackSpace altgr keycode 35 = less keycode 36 = +j shift keycode 36 = +J control keycode 36 = Control_j altgr keycode 36 = greater keycode 37 = +k shift keycode 37 = +K control keycode 37 = Control_k altgr keycode 37 = apostrophe keycode 38 = +l shift keycode 38 = +L control keycode 38 = Control_l altgr keycode 38 = quotedbl keycode 39 = keycode 40 = keycode 41 = keycode 42 = SShift keycode 43 = backslash shift keycode 43 = bar keycode 44 = +z shift keycode 44 = +Z control keycode 44 = Control_z keycode 45 = +x shift keycode 45 = +X control keycode 45 = Control_x keycode 46 = +c shift keycode 46 = +C control keycode 46 = Control_c keycode 47 = +v shift keycode 47 = +V control keycode 47 = Control_v keycode 48 = +b shift keycode 48 = +B altgr keycode 48 = grave control keycode 48 = Control_b keycode 49 = +n shift keycode 49 = +N control keycode 49 = Control_n altgr keycode 49 = asciitilde keycode 50 = +m shift keycode 50 = +M control keycode 50 = Control_m altgr keycode 50 = colon keycode 51 = keycode 52 = period shift keycode 52 = comma altgr keycode 52 = semicolon keycode 53 = slash shift keycode 53 = question altgr keycode 53 = backslash keycode 54 = SShift keycode 55 = keycode 56 = SAltGr keycode 57 = space control keycode 57 = nul keycode 58 = keycode 59 = keycode 60 = keycode 61 = keycode 62 = keycode 63 = keycode 64 = keycode 65 = keycode 66 = keycode 67 = keycode 68 = keycode 69 = keycode 70 = keycode 71 = keycode 72 = keycode 73 = keycode 74 = keycode 75 = keycode 76 = keycode 77 = keycode 78 = keycode 79 = keycode 80 = keycode 81 = keycode 82 = keycode 83 = keycode 84 = keycode 85 = keycode 86 = keycode 87 = keycode 88 = keycode 89 = keycode 90 = keycode 91 = keycode 92 = keycode 93 = keycode 94 = keycode 95 = keycode 96 = keycode 97 = keycode 98 = keycode 99 = keycode 100 = keycode 101 = keycode 102 = keycode 103 = Up keycode 104 = keycode 105 = Left keycode 106 = Right keycode 107 = keycode 108 = Down keycode 109 = keycode 110 = keycode 111 = keycode 112 = keycode 113 = keycode 114 = keycode 115 = keycode 116 = keycode 117 = keycode 118 = keycode 119 = keycode 120 = keycode 121 = keycode 122 = keycode 123 = keycode 124 = keycode 125 = keycode 126 = keycode 127 = keycode 128 = keycode 129 = keycode 130 = keycode 131 = keycode 132 = keycode 133 = keycode 134 = keycode 135 = keycode 136 = keycode 137 = keycode 138 = keycode 139 = keycode 140 = keycode 141 = keycode 142 = keycode 143 = keycode 144 = keycode 145 = keycode 146 = keycode 147 = keycode 148 = keycode 149 = keycode 150 = keycode 151 = keycode 152 = keycode 153 = keycode 154 = keycode 155 = keycode 156 = keycode 157 = keycode 158 = keycode 159 = keycode 160 = keycode 161 = keycode 162 = keycode 163 = keycode 164 = keycode 165 = keycode 166 = keycode 167 = keycode 168 = keycode 169 = keycode 170 = keycode 171 = keycode 172 = keycode 173 = keycode 174 = keycode 175 = keycode 176 = keycode 177 = keycode 178 = keycode 179 = keycode 180 = keycode 181 = keycode 182 = keycode 183 = keycode 184 = keycode 185 = keycode 186 = keycode 187 = keycode 188 = keycode 189 = keycode 190 = keycode 191 = keycode 192 = keycode 193 = keycode 194 = keycode 195 = keycode 196 = keycode 197 = keycode 198 = keycode 199 = keycode 200 = keycode 201 = keycode 202 = keycode 203 = keycode 204 = keycode 205 = keycode 206 = keycode 207 = keycode 208 = keycode 209 = keycode 210 = keycode 211 = keycode 212 = keycode 213 = keycode 214 = keycode 215 = keycode 216 = keycode 217 = keycode 218 = keycode 219 = keycode 220 = keycode 221 = keycode 222 = keycode 223 = keycode 224 = keycode 225 = keycode 226 = keycode 227 = keycode 228 = keycode 229 = keycode 230 = keycode 231 = keycode 232 = keycode 233 = keycode 234 = keycode 235 = keycode 236 = keycode 237 = keycode 238 = keycode 239 = keycode 240 = keycode 241 = keycode 242 = keycode 243 = keycode 244 = keycode 245 = keycode 246 = keycode 247 = keycode 248 = keycode 249 = keycode 250 = keycode 251 = keycode 252 = keycode 253 = keycode 254 = keycode 255 = |
Damit diese keymap nach dem Boot verwendet wird, lade ich sie über /etc/rc.local
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
pi@raspberrypi:~ $ cat /etc/rc.local #!/bin/sh -e # # rc.local # # This script is executed at the end of each multiuser runlevel. # Make sure that the script will "exit 0" on success or any other # value on error. # # In order to enable or disable this script just change the execution # bits. # # By default this script does nothing. # Print the IP address _IP=$(hostname -I) || true if [ "$_IP" ]; then printf "My IP address is %s\n" "$_IP" fi /bin/loadkeys /home/pi/i2c-keypad.map exit 0 |
Und dann hat es auch schon funktioniert. Dazu sei noch gesagt, dass ich das Light Image des Raspbians nutze. Wenn man auch Desktop benutzen will, muss man noch weitere Konfigurationen machen.
Hier noch ein ganz kurzes Demo-Video
Pingback: Keyboard Mapping – Blak_RPI